package pl.elka.pszt.model.literal;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import pl.elka.pszt.model.argument.Argument;

/**
 * Klasa pomocnicza przy nadawaniu unikalnych identyfikatorow dla literalom.
 * 
 * @author Andrzej Makarewicz
 * 
 */
public class LiteralHelper {
	
	private AtomicInteger idGenerator = new AtomicInteger();
	private Map<String, Predicat> predicats = new HashMap<String, Predicat>();
	private Map<Integer, String> predicatNames = new HashMap<Integer, String>();
	
	/**
	 * 
	 * @param name
	 * @param argumentsNumber
	 * @return predykat o podanej nazwie, tworzony jezeli jeszcze nie istnieje
	 */
	public Predicat getOrCreatePredicat(String name, int argumentsNumber) {
		if (name == null || argumentsNumber < 0) throw new IllegalArgumentException();
		
		Predicat predicat = predicats.get(name);
		if (predicat == null) {
			int id = idGenerator.getAndIncrement();
			predicat = new Predicat(id, argumentsNumber);
			predicats.put(name, predicat);
			predicatNames.put(id, name);
		}
		
		return predicat;
	}
	
	/**
	 * 
	 * @param name
	 * @param isPositive
	 *            czy niezanegowany
	 * @param arguments
	 * @return stworzony literal o zadanej nazwie predykatu (tworzy predykat
	 *         jezeli nie istnieje) oraz argumentach i okresleniu zanegowania
	 */
	public Literal createLiteral(String name, boolean isPositive, List<Argument> arguments) {
		if (name == null || arguments == null) throw new NullPointerException();
		Predicat predicat = getOrCreatePredicat(name, arguments.size());
		return new Literal(predicat, isPositive, arguments, this);
	}
	
	/**
	 * 
	 * @param id
	 * @return predykat dla danego id lub <code>null</code> jesli nie wystepuje
	 */
	public Predicat getPredicatById(int id) {
		String name = predicatNames.get(id);
		return name == null ? null : predicats.get(name);
	}
	
	/**
	 * 
	 * @param argument
	 * @return nazwa danego predykatu
	 */
	public String getPredicatName(Predicat predicat) {
		return predicatNames.get(predicat.getId());
	}
	
	/**
	 * Czysci mapowania predykatow i nazw, zeruje identyfikatory. Nazelzy
	 * wywolac gdy ladowana jest nowa baza wiedzy.
	 */
	public void clear() {
		idGenerator = new AtomicInteger();
		predicats.clear();
		predicatNames.clear();
	}
}
